import { memo, useMemo, useState } from 'react';
import { Button, Modal, Row, Space } from 'antd';
import {
  CaretRightOutlined,
  CaretDownOutlined,
  DeleteOutlined,
  ExclamationCircleOutlined,
  DownloadOutlined,
  FormOutlined,
} from '@ant-design/icons';
import ProTable, { ProColumns, ProTableProps } from '@ant-design/pro-table';
import { ProFormColumnsType } from '@ant-design/pro-form';
import SearchForm from '@/components/SearchForm';
import UploadBtn from '../UploadBtn';
import { FormInstance } from 'antd/es/form/Form';

const { confirm } = Modal;

interface Props {
  /** @description 自定义的搜索表单配置项 */
  searchParams?: {
    columns?: ProFormColumnsType[];
    labelSelect?: { [key: string]: string };
    form?: FormInstance;
  };
  /** @description 自定义表格折叠内容 */
  expandedRowRender?: (record: any) => void;
  /** @description 自带的操作栏 */
  action?: string[];
  onHandleActionClick?: (
    type: 'edit' | 'delete' | 'add' | 'download' | 'upload',
    record?: any,
    index?: number,
  ) => void;
  actionRef?: any;
  /** @description 导入的url */
  actionUrl?: string;
}

/**
 * TODO: 封装表格常见功能 （ProTable + Search）
 * @description 自定义表格折叠部分 其它皆可配 默认自带操作栏
 */
function TemplateProTable<T = any>(
  props: ProTableProps<Record<string, any>, Record<string, any>> & Props,
) {
  const {
    expandedRowRender,
    searchParams,
    action,
    onHandleActionClick,
    actionRef,
  } = props;

  const [params, setParams] = useState({}); // 监听自定义search 触发请求

  const actionColumn = {
    title: 'Action',
    key: 'action',
    hideInForm: true,
    hideInDescriptions: true,
    align: 'center' as const,
    width: 150,
    render: (_: any, record: any, index: number) => (
      <Space>
        {[
          action?.includes('edit')
            ? EditDom(record, index, onHandleActionClick)
            : null,
          action?.includes('delete')
            ? DeleteDom(record, index, onHandleActionClick)
            : null,
        ]}
      </Space>
    ),
    shouldCellUpdate: () => true,
  };

  // 优化性能 减少渲染
  const formatColumns = useMemo(() => {
    let arr = props.columns;
    if (
      action &&
      action.length &&
      props.columns &&
      (action?.includes('edit') || action?.includes('delete'))
    ) {
      arr = arr?.concat([actionColumn]);
    }
    return arr?.map((column) => ({
      ...column,
      shouldCellUpdate:
        column.shouldCellUpdate !== undefined
          ? column.shouldCellUpdate
          : (record: any, prev: any) => {
              // eslint-disable-next-line @typescript-eslint/ban-ts-comment
              // @ts-ignore
              return record[column.dataIndex] !== prev[column.dataIndex];
            },
    }));
  }, [props.columns]);

  return (
    <div>
      <Row justify="space-between" style={{ paddingLeft: '24px' }}>
        {/* 这里给导入导出按钮 预留位置 等方案确认 */}
        <Space>
          {action?.length ? (
            <Button
              key="add"
              type="primary"
              onClick={() => onHandleActionClick && onHandleActionClick('add')}
              loading={props.loading}
            >
              Add
            </Button>
          ) : (
            ''
          )}
          {action?.includes('download') && (
            <Button
              key="download"
              type="ghost"
              icon={<DownloadOutlined />}
              onClick={() =>
                onHandleActionClick && onHandleActionClick('download')
              }
              loading={props.loading}
            >
              Export
            </Button>
          )}
          {props.actionUrl && action?.includes('upload') && (
            <UploadBtn
              key="upload"
              onAfterSuccess={() =>
                onHandleActionClick && onHandleActionClick('upload')
              }
              url={props.actionUrl}
            />
          )}
        </Space>
        {searchParams && (
          <SearchForm
            onSearch={(val) => {
              setParams(val);
              if (actionRef && actionRef.current) {
                actionRef.current.setPageInfo({
                  current: 1,
                });
              }
            }}
            propsForm={searchParams.form}
            {...searchParams}
          />
        )}
      </Row>
      <ProTable<T | any>
        bordered
        search={false}
        rowKey="id"
        size="middle"
        sticky
        pagination={{ defaultPageSize: 10 }}
        expandable={
          expandedRowRender
            ? {
                expandedRowRender,
                expandIcon: ({ expanded, onExpand, record }) =>
                  expanded ? (
                    <CaretDownOutlined onClick={(e) => onExpand(record, e)} />
                  ) : (
                    <CaretRightOutlined onClick={(e) => onExpand(record, e)} />
                  ),
              }
            : undefined
        }
        {...props}
        // columns={props.columns?.concat([actionColumn])}
        columns={formatColumns as ProColumns[]}
        params={params}
        request={async (param, sort, filter) => {
          const data = {
            ...param,
            ...params,
            page: param.current,
          };
          delete data.current;
          const res: any =
            props.request && (await props.request(data, sort, filter));
          return res;
        }}
      />
    </div>
  );
}

export default memo(TemplateProTable);

export const DeleteDom = (
  record: any,
  index: number,
  callback?: (
    type: 'edit' | 'delete' | 'add',
    record: any,
    index: number,
  ) => void,
) => (
  <DeleteOutlined
    className="operate-icon"
    key="delete"
    onClick={() => {
      confirm({
        title: 'Do you Want to delete This items?',
        icon: <ExclamationCircleOutlined />,
        onOk() {
          callback && callback('delete', record, index);
        },
      });
    }}
  />
);
export const EditDom = (
  record: any,
  index: number,
  callback?: (
    type: 'edit' | 'delete' | 'add',
    record: any,
    index: number,
  ) => void,
) => (
  <FormOutlined
    className="operate-icon"
    key="edit"
    onClick={() => {
      callback && callback('edit', record, index);
    }}
  />
);
